home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / psi110g.zip / TCPSUBR.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  9KB  |  353 lines

  1. /* Low level TCP routines:
  2.  *  control block management
  3.  *  sequence number logical operations
  4.  *  state transitions
  5.  *  RTT cacheing
  6.  *  garbage collection
  7.  *
  8.  * Copyright 1991 Phil Karn, KA9Q
  9.  */
  10. #include "global.h"
  11. #include "timer.h"
  12. #include "mbuf.h"
  13. #include "netuser.h"
  14. #include "internet.h"
  15. #include "iface.h"
  16. #include "tcp.h"
  17. #include "ip.h"
  18.   
  19. /* TCP connection states */
  20. char *Tcpstates[] = {
  21.     "",
  22.     "Closed",
  23.     "Listen",
  24.     "SYN sent",
  25.     "SYN received",
  26.     "Established",
  27.     "FIN wait 1",
  28.     "FIN wait 2",
  29.     "Close wait",
  30.     "Last ACK",
  31.     "Closing",
  32.     "Time wait"
  33. };
  34.   
  35. /* TCP closing reasons */
  36. char *Tcpreasons[] = {
  37.     "Normal",
  38.     "Reset/Refused",
  39.     "Timeout",
  40.     "ICMP"
  41. };
  42. struct tcb *Tcbs;       /* Head of control block list */
  43. int16 Tcp_mss = DEF_MSS;    /* Maximum segment size to be sent with SYN */
  44. int32 Tcp_irtt = DEF_RTT;   /* Initial guess at round trip time */
  45. int Tcp_retries = DEF_RETRIES;    /* Max retries before resetting tcb */
  46. int Tcp_trace;          /* State change tracing flag */
  47. int Tcp_syndata;
  48. struct tcp_rtt Tcp_rtt[RTTCACHE];
  49. struct mib_entry Tcp_mib[] = {
  50.     NULLCHAR,       0,
  51.     "tcpRtoAlgorithm",  4,  /* Van Jacobsen's algorithm */
  52.     "tcpRtoMin",        0,  /* No lower bound */
  53.     "tcpRtoMax",        MAXINT32,   /* No upper bound */
  54.     "tcpMaxConn",       -1L,    /* No limit */
  55.     "tcpActiveOpens",   0,
  56.     "tcpPassiveOpens",  0,
  57.     "tcpAttemptFails",  0,
  58.     "tcpEstabResets",   0,
  59.     "tcpCurrEstab",     0,
  60.     "tcpInSegs",        0,
  61.     "tcpOutSegs",       0,
  62.     "tcpRetransSegs",   0,
  63.     NULLCHAR,       0,  /* Connection state goes here */
  64.     "tcpInErrs",        0,
  65.     "tcpOutRsts",       0,
  66. };
  67.   
  68.   
  69. /* Look up TCP connection
  70.  * Return TCB pointer or NULLTCB if nonexistant.
  71.  * Also move the entry to the top of the list to speed future searches.
  72.  */
  73. struct tcb *
  74. lookup_tcb(conn)
  75. register struct connection *conn;
  76. {
  77.     register struct tcb *tcb;
  78.     struct tcb *tcblast = NULLTCB;
  79.   
  80.     for(tcb=Tcbs;tcb != NULLTCB;tcblast = tcb,tcb = tcb->next){
  81.         /* Yet another structure compatibility hack */
  82.         if(conn->remote.port == tcb->conn.remote.port
  83.             && conn->local.port == tcb->conn.local.port
  84.             && conn->remote.address == tcb->conn.remote.address
  85.         && conn->local.address == tcb->conn.local.address){
  86.             if(tcblast != NULLTCB){
  87.                 /* Move to top of list */
  88.                 tcblast->next = tcb->next;
  89.                 tcb->next = Tcbs;
  90.                 Tcbs = tcb;
  91.             }
  92.             return tcb;
  93.         }
  94.   
  95.     }
  96.     return NULLTCB;
  97. }
  98.   
  99.     /*
  100.     struct iface *ifp;
  101.   
  102.     if(ismyaddr(addr) != NULLIF)
  103.         return addr;
  104.   
  105.     rp = rt_lookup(addr);
  106.     if(rp != NULLROUTE && rp->iface != NULLIF)
  107.         ifp = rp->iface;
  108.     */
  109.   
  110. /* Create a TCB, return pointer. Return pointer if TCB already exists. */
  111. struct tcb *
  112. create_tcb(conn)
  113. struct connection *conn;
  114. {
  115.     struct tcb *tcb;
  116.     struct route *rp;
  117.     struct tcp_rtt *tp;
  118.   
  119.     if((tcb = lookup_tcb(conn)) != NULLTCB)
  120.         return tcb;
  121.     tcb = (struct tcb *)callocw(1,sizeof (struct tcb));
  122.     ASSIGN(tcb->conn,*conn);
  123.   
  124.     tcb->state = TCP_CLOSED;
  125.     tcb->ssthresh = 65535U;
  126.     /* All this is now done in open_tcp() and tcp_in() - WG7J */
  127.     tcb->cwind = tcb->mss = Tcp_mss;
  128.     if((tp = rtt_get(tcb->conn.remote.address)) != NULLRTT){
  129.         tcb->srtt = tp->srtt;
  130.         tcb->mdev = tp->mdev;
  131.     } else {
  132.         tcb->srtt = Tcp_irtt;   /* mdev = 0 */
  133.     }
  134.     /* Initialize timer intervals */
  135.     set_timer(&tcb->timer,tcb->srtt);
  136.     tcb->timer.func = tcp_timeout;
  137.     tcb->timer.arg = tcb;
  138.   
  139.     /* point to the default interface parms block */
  140.     tcb->parms = &def_iftcp;
  141.   
  142.     tcb->next = Tcbs;
  143.     Tcbs = tcb;
  144.     return tcb;
  145. }
  146.   
  147. /* Close our TCB */
  148. void
  149. close_self(tcb,reason)
  150. register struct tcb *tcb;
  151. int reason;
  152. {
  153.     struct reseq *rp1;
  154.     register struct reseq *rp;
  155.   
  156.     if(tcb == NULLTCB)
  157.         return;
  158.   
  159.     stop_timer(&tcb->timer);
  160.     tcb->reason = reason;
  161.   
  162.     /* Flush reassembly queue; nothing more can arrive */
  163.     for(rp = tcb->reseq;rp != NULLRESEQ;rp = rp1){
  164.         rp1 = rp->next;
  165.         free_p(rp->bp);
  166.         free((char *)rp);
  167.     }
  168.     tcb->reseq = NULLRESEQ;
  169.     setstate(tcb,TCP_CLOSED);
  170. }
  171.   
  172. /* Sequence number comparisons
  173.  * Return true if x is between low and high inclusive,
  174.  * false otherwise
  175.  */
  176. int
  177. seq_within(x,low,high)
  178. register int32 x,low,high;
  179. {
  180.     if(low <= high){
  181.         if(low <= x && x <= high)
  182.             return 1;
  183.     } else {
  184.         if(low >= x && x >= high)
  185.             return 1;
  186.     }
  187.     return 0;
  188. }
  189. int
  190. seq_lt(x,y)
  191. register int32 x,y;
  192. {
  193.     return (long)(x-y) < 0;
  194. }
  195. #ifdef  notdef
  196. int
  197. seq_le(x,y)
  198. register int32 x,y;
  199. {
  200.     return (long)(x-y) <= 0;
  201. }
  202. #endif  /* notdef */
  203. int
  204. seq_gt(x,y)
  205. register int32 x,y;
  206. {
  207.     return (long)(x-y) > 0;
  208. }
  209. int
  210. seq_ge(x,y)
  211. register int32 x,y;
  212. {
  213.     return (long)(x-y) >= 0;
  214. }
  215.   
  216. void
  217. setstate(tcb,newstate)
  218. register struct tcb *tcb;
  219. register int newstate;
  220. {
  221.     register char oldstate;
  222.   
  223.     oldstate = tcb->state;
  224.     tcb->state = newstate;
  225.     if(Tcp_trace)
  226.         printf("TCB %lx %s -> %s\n",ptol(tcb),
  227.         Tcpstates[oldstate],Tcpstates[newstate]);
  228.   
  229.     /* Update MIB variables */
  230.     switch(oldstate){
  231.         case TCP_CLOSED:
  232.             if(newstate == TCP_SYN_SENT)
  233.                 tcpActiveOpens++;
  234.             break;
  235.         case TCP_LISTEN:
  236.             if(newstate == TCP_SYN_RECEIVED)
  237.                 tcpPassiveOpens++;
  238.             break;
  239.         case TCP_SYN_SENT:
  240.             if(newstate == TCP_CLOSED)
  241.                 tcpAttemptFails++;
  242.             break;
  243.         case TCP_SYN_RECEIVED:
  244.         switch(newstate){
  245.             case TCP_CLOSED:
  246.             case TCP_LISTEN:
  247.                 tcpAttemptFails++;
  248.                 break;
  249.         }
  250.             break;
  251.         case TCP_ESTABLISHED:
  252.         case TCP_CLOSE_WAIT:
  253.         switch(newstate){
  254.             case TCP_CLOSED:
  255.             case TCP_LISTEN:
  256.                 tcpEstabResets++;
  257.                 break;
  258.         }
  259.             tcpCurrEstab--;
  260.             break;
  261.     }
  262.     if(newstate == TCP_ESTABLISHED || newstate == TCP_CLOSE_WAIT)
  263.         tcpCurrEstab++;
  264.   
  265.     if(tcb->s_upcall)
  266.         (*tcb->s_upcall)(tcb,oldstate,newstate);
  267.   
  268.     switch(newstate){
  269.         case TCP_SYN_RECEIVED:  /***/
  270.         case TCP_ESTABLISHED:
  271.         /* Notify the user that he can begin sending data */
  272.             if(tcb->t_upcall)
  273.                 (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  274.             break;
  275.     }
  276. }
  277. /* Round trip timing cache routines.
  278.  * These functions implement a very simple system for keeping track of
  279.  * network performance for future use in new connections.
  280.  * The emphasis here is on speed of update (rather than optimum cache hit
  281.  * ratio) since rtt_add is called every time a TCP connection updates
  282.  * its round trip estimate.
  283.  */
  284. void
  285. rtt_add(addr,rtt)
  286. int32 addr;     /* Destination IP address */
  287. int32 rtt;
  288. {
  289.     register struct tcp_rtt *tp;
  290.     int32 abserr;
  291.   
  292.     if(addr == 0)
  293.         return;
  294.     tp = &Tcp_rtt[(unsigned short)addr % RTTCACHE];
  295.     if(tp->addr != addr){
  296.         /* New entry */
  297.         tp->addr = addr;
  298.         tp->srtt = rtt;
  299.         tp->mdev = 0;
  300.     } else {
  301.         /* Run our own SRTT and MDEV integrators, with rounding */
  302.         abserr = (rtt > tp->srtt) ? rtt - tp->srtt : tp->srtt - rtt;
  303.         tp->srtt = ((AGAIN-1)*tp->srtt + rtt + (AGAIN/2)) >> LAGAIN;
  304.         tp->mdev = ((DGAIN-1)*tp->mdev + abserr + (DGAIN/2)) >> LDGAIN;
  305.     }
  306. }
  307. struct tcp_rtt *
  308. rtt_get(addr)
  309. int32 addr;
  310. {
  311.     register struct tcp_rtt *tp;
  312.   
  313.     if(addr == 0)
  314.         return NULLRTT;
  315.     tp = &Tcp_rtt[(unsigned short)addr % RTTCACHE];
  316.     if(tp->addr != addr)
  317.         return NULLRTT;
  318.     return tp;
  319. }
  320.   
  321. #ifndef LINUX
  322.   
  323. /* TCP garbage collection - called by storage allocator when free space
  324.  * runs low. The send and receive queues are crunched. If the situation
  325.  * is red, the resequencing queue is discarded; otherwise it is
  326.  * also crunched.
  327.  */
  328. void
  329. tcp_garbage(red)
  330. int red;
  331. {
  332.     register struct tcb *tcb;
  333.     struct reseq *rp,*rp1;
  334.   
  335.     for(tcb = Tcbs;tcb != NULLTCB;tcb = tcb->next){
  336.         mbuf_crunch(&tcb->rcvq);
  337.         mbuf_crunch(&tcb->sndq);
  338.         for(rp = tcb->reseq;rp != NULLRESEQ;rp = rp1){
  339.             rp1 = rp->next;
  340.             if(red){
  341.                 free_p(rp->bp);
  342.                 free((char *)rp);
  343.             } else {
  344.                 mbuf_crunch(&rp->bp);
  345.             }
  346.         }
  347.         if(red)
  348.             tcb->reseq = NULLRESEQ;
  349.     }
  350. }
  351. #endif /* LINUX */
  352.   
  353.